/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools resize node
 */

#ifndef HMFS_NODE_H
#define HMFS_NODE_H

#include "hmfs_common.h"
#include "hmfs_fs.h"
#include "hmfs_io.h"
#include "hmfs_log.h"
#include "resize_data.h"
#include "securec.h"

namespace OHOS {
namespace Hmfs {
enum {
    COLD_BIT_SHIFT = 0,
    FSYNC_BIT_SHIFT,
    DENT_BIT_SHIFT,
    OFFSET_BIT_SHIFT
};

#define XATTR_NODE_OFFSET    ((((uint32_t)-1) << OFFSET_BIT_SHIFT) >> OFFSET_BIT_SHIFT)

unsigned long CurrentNatAddr(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo, uint32_t start);
bool IsRecoverableDnode(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo, NodeData *nodeBlock);
int32_t LookupNatInJournal(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo, uint32_t nodeId, NatEntry *rawNat);
void GetNatEntry(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo, uint32_t nodeId, NatEntry *rawNat);
uint32_t GetAddressesPerPage(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo,
    NodeData *nodeBlock, NodeData *inodeBlock);
uint32_t CalculateBlockIndex(uint32_t nodeOffset, NodeData *nodeBlock);

inline int32_t IsInode(NodeData *node)
{
    return ((node)->footer.nodeId == (node)->footer.inodeNumber);
}

inline void NodeInfoFromRawNat(NodeInfo *nodeInfo, NatEntry *rawNat)
{
    nodeInfo->inodeNumber = LE32ToNative(rawNat->inodeNumber);
    nodeInfo->blockAddr = LE32ToNative(rawNat->blockId);
    nodeInfo->version = rawNat->version;
}

inline void GetNodeInfo(std::shared_ptr<HmfsSuperBlockInfo> &superBlockInfo, uint32_t nodeId, NodeInfo *nodeInfo)
{
    NatEntry rawNat;
    nodeInfo->nodeId = nodeId;
    GetNatEntry(superBlockInfo, nodeId, &rawNat);
    NodeInfoFromRawNat(nodeInfo, &rawNat);
}

inline uint32_t *BlockAddressInINode(NodeData *node)
{
    return node->inode.dataBlocksAddr + HmfsCommon::GetInstance().GetExtraIsize(&node->inode);
}

inline uint32_t *BlockAddressInNode(NodeData *node)
{
    return IsInode(node) ? BlockAddressInINode(node) : node->directNode.addr;
}

inline uint32_t DatablockAddr(NodeData *nodePage, uint32_t offset)
{
    uint32_t *addrArray = BlockAddressInNode(nodePage);
    return LE32ToNative(addrArray[offset]);
}

inline uint32_t OfsOfNode(NodeData *nodeBlock)
{
    unsigned flag = LE32ToNative(nodeBlock->footer.flag);
    return flag >> OFFSET_BIT_SHIFT;
}

inline bool IsSetCheckPointFlags(CheckPointData *checkPoint, uint32_t inputFlag)
{
    uint32_t flag = LE32ToNative(checkPoint->checkPointFlags);
    return flag & inputFlag ? 1 : 0;
}

inline uint64_t GetCheckpointCrc(CheckPointData *checkPoint)
{
    size_t offset = LE32ToNative(checkPoint->checksumOffset);
    return LE32ToNative(*(reinterpret_cast<uint32_t *>(reinterpret_cast<unsigned char *>(checkPoint) + offset)));
}

inline int32_t IsNode(NodeData *nodeBlock, int type)
{
    return LE32ToNative(nodeBlock->footer.flag) & (1 << type);
}
} // namespace Hmfs
} // namespace OHOS
#endif // HMFS_NODE_H
